from __future__ import absolute_import
from riakmodels.property import Property
from riakmodels.protorpc import messages
from riakmodels.protorpc import protojson

class MessageProperty(Property):
    ''' Used to store google protorpc Messages.
    
        refer to :class:`riakmodels.protorpc.messages.Message`
    '''
    def __init__(self, **kwargs):
        self.message_type = kwargs.pop('message', messages.Message)
        
        if 'indexed_fields' in kwargs:
            kwargs['indexed'] = True
            
        self.indexed_fields = kwargs.pop('indexed_fields', [])
        
        kwargs['type'] = self.message_type
        # TODO: handle indexed properties
        super(MessageProperty, self).__init__(**kwargs)
        
    def get_index_types(self):
        for field in self.indexed_fields:
            if not hasattr(self.message_type, field):
                raise Exception("Cannot index missing field %s" % field)
            field_class = getattr(self.message_type, field)
            if isinstance(field_class, (messages.StringField, messages.BytesField)):
                yield 'bin'
            elif isinstance(field_class, (messages.IntegerField)):
                yield 'int'
            else:
                raise Exception('Cannot index message field %s of type %s.' % (field, field_class.__name__))
        
    def get_index_keys(self):
        for field,type in zip(self.indexed_fields, self.get_index_types()):
            field_class = getattr(self.message_type, field)
            key = '%s.%s_%s' % (self.get_id(), field_class.number, type)
            yield key
            
    def encode_index_values(self, v):
        for field in self.indexed_fields:
            field_val = getattr(v, field)
            yield field_val
        
    def encode_single(self, v):
        if not isinstance(v, self.message_type):
            raise ValueError("MessageProperty property %s value must be a Message. Got %s" % (self.get_id(), type(v)))
        return protojson.encode_message(v)

    def encode_repeated(self, v):
        l = []
        for i, val in enumerate(v):
            if not isinstance(val, self.message_type):
                raise ValueError("MessageProperty property %s value must be a LIST of Message. Got %s at %s" % (self.get_id(), type(val), i))
            l.append(protojson.encode_message(val))
        return l
        
    def decode_single(self, v):
        return protojson.decode_message(self.message_type, v)
    
    def decode_repeated(self, v):
        l = []
        for i, val in enumerate(v):
            l.append(protojson.decode_message(self.message_type, val))
        return l
